package cn.ztuo.bitrade.runnable;

import cn.ztuo.bitrade.Trader.CoinTrader;
import cn.ztuo.bitrade.constant.BooleanEnum;
import cn.ztuo.bitrade.entity.*;
import cn.ztuo.bitrade.service.ExchangeOrderService;
import cn.ztuo.bitrade.service.ExchangeService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.kafka.core.KafkaTemplate;

import java.io.*;
import java.math.BigDecimal;
import java.util.*;

@Slf4j
public class RobotOrderRunnableNewBak implements Runnable {

    public static Map<String, Integer> robotStatusMap = new HashMap<>();
    private KafkaTemplate<String, String> kafkaTemplate;
    private ExchangeOrderService orderService;
    private ExchangeService exchangeService;
    private ExchangeCoin coin;
    private CoinTrader coinTrader;
    private static Map<String, Map<ExchangeOrderDirection, List<ExchangeOrder>>> plateMap = new HashMap<>();


    private volatile static RobotOrderRunnableNewBak robotOrderRunnable;

    private RobotOrderRunnableNewBak() {

    }

    public static void setRoboStatusMap(Map<String, Integer> robotStatusMap) {
        RobotOrderRunnableNewBak.robotStatusMap = robotStatusMap;
    }

    private RobotOrderRunnableNewBak(KafkaTemplate<String, String> kafkaTemplate, ExchangeOrderService orderService, ExchangeCoin coin, CoinTrader coinTrader, ExchangeService exchangeService) {
        this.kafkaTemplate = kafkaTemplate;
        this.orderService = orderService;
        this.coin = coin;
        this.coinTrader = coinTrader;
        this.exchangeService = exchangeService;
    }

    public static RobotOrderRunnableNewBak getInstance(KafkaTemplate<String, String> kafkaTemplate, ExchangeOrderService orderService, ExchangeCoin coin, CoinTrader coinTrader, ExchangeService exchangeService) {

        robotOrderRunnable = new RobotOrderRunnableNewBak(kafkaTemplate, orderService, coin, coinTrader,exchangeService);

        return robotOrderRunnable;
    }

    private void robotAddOrder() {
        try {
            synchronized (coin) {
                log.info("合约机器人--" + coin.getSymbol() + "--下单中.......");
                if (robotStatusMap.get(coin.getSymbol()) == null || robotStatusMap.get(coin.getSymbol()) == 0) {
                    log.info(coin.getSymbol() + "=====机器人已经停止================");
                    return;
                }

                Ticker ticker = getTickerByUrl(coin);
                if (ticker == null) {
                    return;
                }
                log.info("匹配当前 最新价格  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
                List<ExchangeOrder> bids = ticker.getBids();
                List<ExchangeOrder> asks =ticker.getAsks();

                ExchangeTrade trade = new ExchangeTrade();
                trade.setAmount(ticker.getTradeSize());
                trade.setPrice(ticker.getTradePrice());
                trade.setSymbol(coin.getSymbol());
                trade.setTime(Calendar.getInstance().getTimeInMillis());
                trade.setType(1);

                List<ExchangeTrade> list = new ArrayList<>();
                list.add(trade);
                Map<ExchangeOrderDirection, List<ExchangeOrder>> mapPlate = new HashMap<>();
                if (!plateMap.isEmpty() && plateMap.containsKey(coin.getSymbol()) && plateMap.get(coin.getSymbol()) != null) {
                    mapPlate = plateMap.get(coin.getSymbol());
                    List<ExchangeOrder> bidsOld = mapPlate.get(ExchangeOrderDirection.BUY);
                    List<ExchangeOrder> asksOld = mapPlate.get(ExchangeOrderDirection.SELL);
//                    coinTrader.addRobotLimitPriceOrder(bids,asks,bidsOld,asksOld);
//                    coinTrader.addRobotLimitPriceOrder(asks, ExchangeOrderDirection.SELL);
//                    coinTrader.cancelRobotOrder(asksOld, ExchangeOrderDirection.SELL);
                } else {
//                    coinTrader.addRobotLimitPriceOrder(bids, ExchangeOrderDirection.BUY);
//                    coinTrader.addRobotLimitPriceOrder(asks, ExchangeOrderDirection.SELL);
//                    coinTrader.addRobotLimitPriceOrder(bids,asks,new ArrayList<>(),new ArrayList<>());
                }
                coinTrader.handleExchangeTrade(list);


                mapPlate.put(ExchangeOrderDirection.BUY, bids);
                mapPlate.put(ExchangeOrderDirection.SELL, asks);
                plateMap.put(coin.getSymbol(), mapPlate);

                Thread.sleep(4 * 1000);
                exchangeService.robotAddOrder(coin.getSymbol());
            }
        } catch (Exception e) {
            robotStatusMap.put(coin.getSymbol(),0);
            log.error(coin.getSymbol() + "机器人挂单异常={}", e);
        }
    }

    /**
     * 获取 Huobi 交易所的行情
     *
     * @return
     */
    private Ticker getTickerByUrl(ExchangeCoin coin) throws IOException {
        String symbol = coin.getSymbol();
        List<String> listHuobi = new ArrayList<>();
        listHuobi.add("TRX/USDT");
        listHuobi.add("QTUM/USDT");
        listHuobi.add("LTC/USDT");
        listHuobi.add("HT/USDT");
        listHuobi.add("HT/ETH");
        listHuobi.add("HT/BTC");
        listHuobi.add("ETH/USDT");
        listHuobi.add("ETH/BTC");
        listHuobi.add("ETC/USDT");
        listHuobi.add("EOS/USDT");
        listHuobi.add("DOGE/USDT");
        listHuobi.add("DASH/USDT");
        listHuobi.add("BTM/USDT");
        listHuobi.add("BTC/USDT");
        listHuobi.add("BCH/USDT");
        List<String> listBitMax = new ArrayList<>();
        listBitMax.add("BNB/USDT");
        listBitMax.add("BNB/ETH");
        listBitMax.add("BNB/BTC");

        JSONObject tick = null;
        Ticker ticker = null;
        JSONObject depth = null;
        List<ExchangeOrder> bids = new ArrayList<>();
        List<ExchangeOrder> asks = new ArrayList<>();
//        List<ExchangeOrder> delbids = new ArrayList<>();
//        List<ExchangeOrder> delasks = new ArrayList<>();

        if (listBitMax.contains(symbol)) {
              String bitmaxStr = readJsonFile("J:\\source\\bitMax.txt");
              String bnbDepthStr = readJsonFile("J:\\source\\bnbDepth.txt");
//            String bitmaxStr = HttpsUtil.doGet("https://bitmax.io/api/pro/v1/ticker?symbol=" + coin.getSymbol());
//            String bnbDepthStr = HttpsUtil.doGet("https://bitmax.io/api/pro/v1/depth?symbol=" + coin.getSymbol());
            JSONObject forObject = JSON.parseObject(bitmaxStr);
            if (forObject.getInteger("code") == 0) {
                JSONObject json = forObject.getJSONObject("data");
                ticker = new Ticker();
                ticker.setSymbol(coin.getSymbol());
                ticker.setTradePrice(json.getBigDecimal("close"));
                ticker.setTradeSize(json.getBigDecimal("volume"));
                String[] ask = json.getString("ask").replaceAll("\\[", "").replaceAll("]", "").replaceAll("\\\"", "").split(",");
                String[] bid = json.getString("bid").replaceAll("\\[", "").replaceAll("]", "").replaceAll("\\\"", "").split(",");
                log.info("ask----------------" + ask);
                log.info("bid----------------" + bid);
                ticker.setAskPrice(new BigDecimal(ask[0]));
                ticker.setBidPrice(new BigDecimal(bid[0]));
                ;
                ticker.setAskSize(new BigDecimal(ask[1]));
                ticker.setBidSize(new BigDecimal(bid[1]));
            } else {
                return null;
            }
            //添加盘口深度
            depth = JSON.parseObject(bnbDepthStr);
            log.info("bnbDepthStr : " + JSON.toJSONString(bnbDepthStr));
            if (depth.containsKey("code") && "0".equals(depth.getString("code"))) {
                tick = depth.getJSONObject("data").getJSONObject("data");
            }
        }
        //赋值binance最新价格
        Ticker finalTicker = ticker;
        if (ticker != null && StringUtils.isNotBlank(ticker.getSymbol())) {
//            String binanceStr = HttpsUtil.doGet("https://api.binance.com/api/v3/ticker/price");
            String binanceStr = readJsonFile("J:\\source\\binance.txt");
            List<JSONObject> priceList = JSON.parseArray(binanceStr, JSONObject.class);
            if (priceList != null && priceList.size() > 0) {
                priceList.stream().filter(a -> a.getString("symbol").equals(finalTicker.getSymbol().replaceAll("/", ""))).forEach(a -> {
                    finalTicker.setTradePrice(a.getBigDecimal("price"));
                });
                ticker = finalTicker;
            }
        }
        if (!listBitMax.contains(symbol)) {
//            String huobiStr = HttpsUtil.doGet("https://api.huobi.pro/market/tickers");
//            String depthStr = HttpsUtil.doGet("https://api.huobi.pro/market/depth?symbol=" + coin.getSymbol().toLowerCase().replaceAll("/", "") + "&depth=20&type=step0");
            String huobiStr = readJsonFile("J:\\source\\huobi.txt");
            String depthStr = readJsonFile("J:\\source\\testRobot.txt");
            JSONObject jsonObject = JSON.parseObject(huobiStr);
            if (jsonObject.containsKey("status") && jsonObject.getString("status").equals("ok") && jsonObject.containsKey("data")) {
                List<JSONObject> objs = JSON.parseArray(jsonObject.getString("data"), JSONObject.class);
                JSONObject json = objs.stream().filter(a -> symbol.replaceAll("/", "").toUpperCase().equals(a.getString("symbol").toUpperCase())).findAny().get();
                if(json==null){
                    return null;
                }
                ticker = new Ticker();
                ticker.setSymbol(coin.getSymbol());
                ticker.setTradePrice(json.getBigDecimal("close"));
                BigDecimal close_size = json.getBigDecimal("bidSize").compareTo(json.getBigDecimal("askSize")) >= 0 ? json.getBigDecimal("askSize") : json.getBigDecimal("bidSize");
                ticker.setTradeSize(close_size);

            } else {
                return null;
            }

            //添加盘口深度
            depth = JSON.parseObject(depthStr);
            if (depth.containsKey("status") && "ok".equals(depth.getString("status"))) {
                tick = depth.getJSONObject("tick");
            }
        }

        List<JSONArray> bidsArray = JSON.parseArray(tick.getString("bids"), JSONArray.class);
        List<JSONArray> asksArray = JSON.parseArray(tick.getString("asks"), JSONArray.class);
        if (bidsArray.size() > 20) {
            bidsArray = bidsArray.subList(bidsArray.size() - 19, bidsArray.size());
        }
        if (asksArray.size() > 20) {
            asksArray = asksArray.subList(0, 20);
        }
        bidsArray.stream().forEach(bid -> {
            ExchangeOrder order = new ExchangeOrder();
            order.setPrice(new BigDecimal(bid.get(0).toString()));
            order.setAmount(new BigDecimal(bid.get(1).toString()));
            order.setDirection(ExchangeOrderDirection.BUY);
            order.setType(ExchangeOrderType.LIMIT_PRICE);
            order.setTradedAmount(BigDecimal.ZERO);
            bids.add(order);
        });
        asksArray.stream().forEach(ask -> {
            ExchangeOrder order = new ExchangeOrder();
            order.setPrice(new BigDecimal(ask.get(0).toString()));
            order.setAmount(new BigDecimal(ask.get(1).toString()));
            order.setDirection(ExchangeOrderDirection.SELL);
            order.setType(ExchangeOrderType.LIMIT_PRICE);
            order.setTradedAmount(BigDecimal.ZERO);
            asks.add(order);
        });
        bids.sort(Comparator.comparing(ExchangeOrder::getPrice).reversed());
        asks.sort(Comparator.comparing(ExchangeOrder::getPrice));
        ticker.setAsks(asks);
        ticker.setBids(bids);
        return ticker;
    }


    @Override
    public void run() {
        robotAddOrder();
    }

    private ExchangeOrder initRobotExchangeOrder(ExchangeOrderDirection direction, Ticker ticker, boolean isTrade) {
        ExchangeOrder order = new ExchangeOrder();
        order.setBaseSymbol(coin.getBaseSymbol());
        order.setCoinSymbol(coin.getCoinSymbol());
        order.setSymbol(coin.getSymbol());
        order.setOrderResource(ExchangeOrderResource.ROBOT);
        order.setType(ExchangeOrderType.LIMIT_PRICE);
        order.setMarginTrade(BooleanEnum.IS_FALSE);
        order.setDirection(direction);
        order.setTradedAmount(BigDecimal.ZERO);
        order.setMemberId(1L);

        order.setAmount(ticker.getTradeSize().setScale(coin.getCoinScale(), BigDecimal.ROUND_DOWN));
        order.setAmountStr(ticker.getTradeSize().toString());
        order.setPrice(ticker.getTradePrice().setScale(coin.getBaseCoinScale(), BigDecimal.ROUND_DOWN));
        order.setPriceStr(ticker.getTradePrice().toString());

        return order;
    }

    public static String readJsonFile(String fileName) {
        String jsonStr = "";
        try {
            File jsonFile = new File(fileName);
            FileReader fileReader = new FileReader(jsonFile);
            Reader reader = new InputStreamReader(new FileInputStream(jsonFile), "utf-8");
            int ch = 0;
            StringBuffer sb = new StringBuffer();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            fileReader.close();
            reader.close();
            jsonStr = sb.toString();
            return jsonStr;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        String depthStr = readJsonFile("J:\\source\\testRobot.txt");
        JSONObject depth = JSON.parseObject(depthStr);

        List<ExchangeOrder> bids = new ArrayList<>();
        List<ExchangeOrder> asks = new ArrayList<>();

        if (depth.containsKey("status") && "ok".equals(depth.getString("status"))) {
            JSONObject tick = depth.getJSONObject("tick");
            List<JSONArray> bidsArray = JSON.parseArray(tick.getString("bids"), JSONArray.class);

            bidsArray.stream().forEach(bid -> {
                System.out.println(bid.get(0));
            });
        }
    }


    class Ticker {
        private String symbol; //交易对
        private BigDecimal tradePrice; //最新成交价格
        private BigDecimal tradeSize; //最新成交数量
        private BigDecimal askPrice; //卖-价格
        private BigDecimal askSize;//卖-数量
        private BigDecimal bidPrice;//买-价格
        private BigDecimal bidSize;//买-数量

        private List<ExchangeOrder> bids;
        private List<ExchangeOrder> asks;

        public List<ExchangeOrder> getBids() {
            return bids;
        }

        public void setBids(List<ExchangeOrder> bids) {
            this.bids = bids;
        }
        public List<ExchangeOrder> getAsks() {
            return asks;
        }

        public void setAsks(List<ExchangeOrder> asks) {
            this.asks = asks;
        }

        public String getSymbol() {
            return symbol;
        }

        public void setSymbol(String symbol) {
            this.symbol = symbol;
        }

        public BigDecimal getTradePrice() {
            return tradePrice;
        }

        public void setTradePrice(BigDecimal tradePrice) {
            this.tradePrice = tradePrice;
        }

        public BigDecimal getTradeSize() {
            return tradeSize;
        }

        public void setTradeSize(BigDecimal tradeSize) {
            this.tradeSize = tradeSize;
        }

        public BigDecimal getAskPrice() {
            return askPrice;
        }

        public void setAskPrice(BigDecimal askPrice) {
            this.askPrice = askPrice;
        }

        public BigDecimal getAskSize() {
            return askSize;
        }

        public void setAskSize(BigDecimal askSize) {
            this.askSize = askSize;
        }

        public BigDecimal getBidPrice() {
            return bidPrice;
        }

        public void setBidPrice(BigDecimal bidPrice) {
            this.bidPrice = bidPrice;
        }

        public BigDecimal getBidSize() {
            return bidSize;
        }

        public void setBidSize(BigDecimal bidSize) {
            this.bidSize = bidSize;
        }
    }
}